home *** CD-ROM | disk | FTP | other *** search
- /*=========================================================================
- * FILE:
- * junk.c
- *
- * $Header: /private/postgres/src/executor/RCS/ex_junk.c,v 1.4 1992/08/21 05:00:07 mer Exp $
- *
- * DESCRIPTION:
- * Junk attribute support stuff....
- *
- *=========================================================================
- */
-
- #include "executor/executor.h"
-
- extern Node CopyObject();
- extern List MakeTLE();
-
- /*-------------------------------------------------------------------------
- * XXX this stuff should be rewritten to take advantage
- * of ExecProject() and the ProjectionInfo node.
- * -cim 6/3/91
- *
- * An attribute of a tuple living inside the executor, can be
- * either a normal attribute or a "junk" attribute. "junk" attributes
- * never make it out of the executor, i.e. they are never printed,
- * returned or stored in disk. Their only purpose in life is to
- * store some information useful only to the executor, mainly the values
- * of some system attributes like "ctid" or rule locks.
- *
- * The general idea is the following: A target list consists of a list of
- * Resdom nodes & expression pairs. Each Resdom node has an attribute
- * called 'resjunk'. If the value of this attribute is 1 then the
- * corresponding attribute is a "junk" attribute.
- *
- * When we initialize a plan we call 'ExecInitJunkFilter' to create
- * and store the appropriate information in the 'es_junkFilter' attribute of
- * EState.
- *
- * We then execute the plan ignoring the "resjunk" attributes.
- *
- * Finally, when at the top level we get back a tuple, we can call
- * 'ExecGetJunkAttribute' to retrieve the value of the junk attributes we
- * are interested in, and 'ExecRemoveJunk' to remove all the junk attributes
- * from a tuple. This new "clean" tuple is then printed, replaced, deleted
- * or inserted.
- *
- *-------------------------------------------------------------------------
- */
-
- /*-------------------------------------------------------------------------
- * ExecInitJunkFilter
- *
- * Initialize the Junk filter.
- *-------------------------------------------------------------------------
- */
- JunkFilter
- ExecInitJunkFilter(targetList)
- List targetList;
- {
- JunkFilter junkfilter;
- List cleanTargetList;
- int len, cleanLength;
- TupleDescriptor tupType, cleanTupType;
- List t, expr, tle;
- Resdom resdom, cleanResdom;
- int resjunk;
- AttributeNumber resno, cleanResno;
- AttributeNumberPtr cleanMap;
- Size size;
-
- /* ---------------------
- * First find the "clean" target list, i.e. all the entries
- * in the original target list which have a zero 'resjunk'
- * NOTE: make copy of the Resdom nodes, because we have
- * to change the 'resno's...
- * ---------------------
- */
- cleanTargetList = LispNil;
- cleanResno = 1;
-
- foreach (t, targetList) {
- if (tl_is_resdom(CAR(t))) {
- resdom = (Resdom) tl_resdom(CAR(t));
- expr = tl_expr(CAR(t));
- resjunk = get_resjunk(resdom);
- if (resjunk == 0) {
- /*
- * make a copy of the resdom node, changing its resno.
- */
- cleanResdom = (Resdom) CopyObject(resdom);
- set_resno(cleanResdom, cleanResno);
- cleanResno ++;
- /*
- * create a new target list entry
- */
- tle = (List) MakeTLE(cleanResdom, expr);
- cleanTargetList = nappend1(cleanTargetList, tle);
- }
- }
- else {
- List fjListP;
- Fjoin cleanFjoin;
- List cleanFjList;
- List fjList = CAR(t);
- Fjoin fjNode = (Fjoin)tl_node(fjList);
-
- cleanFjoin = (Fjoin)CopyObject(fjNode);
- cleanFjList = lispCons(cleanFjoin, LispNil);
-
- resdom = (Resdom) CAR(get_fj_innerNode(fjNode));
- expr = CADR(get_fj_innerNode(fjNode));
- cleanResdom = (Resdom) CopyObject(resdom);
- set_resno(cleanResdom, cleanResno);
- cleanResno++;
- tle = (List) MakeTLE(cleanResdom, expr);
- set_fj_innerNode(cleanFjoin, tle);
-
- foreach(fjListP, CDR(fjList)) {
-
- resdom = (Resdom) tl_resdom(CAR(fjListP));
- expr = tl_expr(CAR(fjListP));
- cleanResdom = (Resdom) CopyObject(resdom);
- cleanResno++;
- set_resno(cleanResdom, cleanResno);
- /*
- * create a new target list entry
- */
- tle = (List) MakeTLE(cleanResdom, expr);
- cleanFjList = nappend1(cleanFjList, tle);
- }
- nappend1(cleanTargetList, cleanFjList);
- }
- }
-
- /* ---------------------
- * Now calculate the tuple types for the original and the clean tuple
- *
- * XXX ExecTypeFromTL should be used sparingly. Don't we already
- * have the tupType corresponding to the targetlist we are passed?
- * -cim 5/31/91
- * ---------------------
- */
- tupType = (TupleDescriptor) ExecTypeFromTL(targetList);
- cleanTupType = (TupleDescriptor) ExecTypeFromTL(cleanTargetList);
-
- len = ExecTargetListLength(targetList);
- cleanLength = ExecTargetListLength(cleanTargetList);
-
- /* ---------------------
- * Now calculate the "map" between the original tuples attributes
- * and the "clean" tuple's attributes.
- *
- * The "map" is an array of "cleanLength" attribute numbers, i.e.
- * one entry for every attribute of the "clean" tuple.
- * The value of this entry is the attribute number of the corresponding
- * attribute of the "original" tuple.
- * ---------------------
- */
- if (cleanLength > 0) {
- size = cleanLength * sizeof(AttributeNumber);
- cleanMap = (AttributeNumberPtr) palloc(size);
- cleanResno = 1;
- foreach (t, targetList) {
- if (tl_is_resdom(CAR(t))) {
- resdom = (Resdom) tl_resdom(CAR(t));
- expr = tl_expr(CAR(t));
- resjunk = get_resjunk(resdom);
- if (resjunk == 0) {
- cleanMap[cleanResno-1] = get_resno(resdom);
- cleanResno ++;
- }
- }
- else {
- List fjListP;
- List fjList = CAR(t);
- Fjoin fjNode = (Fjoin)CAR(fjList);
-
- resdom = (Resdom) CAR(get_fj_innerNode(fjNode));
- cleanMap[cleanResno-1] = get_resno(resdom);
- cleanResno++;
-
- foreach(fjListP, CDR(fjList)) {
- resdom = (Resdom) tl_resdom(CAR(fjListP));
- cleanMap[cleanResno-1] = get_resno(resdom);
- cleanResno++;
- }
- }
- }
- } else {
- cleanMap = NULL;
- }
-
- /* ---------------------
- * Finally create and initialize the JunkFilter.
- * ---------------------
- */
- junkfilter = (JunkFilter) RMakeJunkFilter();
-
- set_jf_targetList(junkfilter, targetList);
- set_jf_length(junkfilter, len);
- set_jf_tupType(junkfilter, tupType);
- set_jf_cleanTargetList(junkfilter, cleanTargetList);
- set_jf_cleanLength(junkfilter, cleanLength);
- set_jf_cleanTupType(junkfilter, cleanTupType);
- set_jf_cleanMap(junkfilter, cleanMap);
-
- return(junkfilter);
-
- }
-
- /*-------------------------------------------------------------------------
- * ExecGetJunkAttribute
- *
- * Given a tuple (slot), the junk filter and a junk attribute's name,
- * extract & return the value of this attribute.
- *
- * It returns false iff no junk attribute with such name was found.
- *
- * NOTE: isNull might be NULL !
- *-------------------------------------------------------------------------
- */
- bool
- ExecGetJunkAttribute(junkfilter, slot, attrName, value, isNull)
- JunkFilter junkfilter;
- TupleTableSlot slot;
- Name attrName;
- Datum *value;
- Boolean *isNull;
- {
- List targetList;
- List t;
- Resdom resdom;
- AttributeNumber resno;
- Name resname;
- int resjunk;
- TupleDescriptor tupType;
- HeapTuple tuple;
-
- /* ---------------------
- * first look in the junkfilter's target list for
- * an attribute with the given name
- * ---------------------
- */
- resno = InvalidAttributeNumber;
- targetList = get_jf_targetList(junkfilter);
-
- foreach (t, targetList) {
- resdom = (Resdom) tl_resdom(CAR(t));
- resname = get_resname(resdom);
- resjunk = get_resjunk(resdom);
- if (resjunk != 0 && NameIsEqual(resname, attrName)) {
- /* We found it ! */
- resno = get_resno(resdom);
- break;
- }
- }
-
- if (resno == InvalidAttributeNumber) {
- /* Ooops! We couldn't find this attribute... */
- return(false);
- }
-
- /* ---------------------
- * Now extract the attribute value from the tuple.
- * ---------------------
- */
- tuple = (HeapTuple) ExecFetchTuple((Pointer) slot);
- tupType = (TupleDescriptor) get_jf_tupType(junkfilter);
-
- *value = (Datum)
- heap_getattr(tuple, InvalidBuffer, resno, tupType, isNull);
-
- return true;
- }
-
- /*-------------------------------------------------------------------------
- * ExecRemoveJunk
- *
- * Construct and return a tuple with all the junk attributes removed.
- *-------------------------------------------------------------------------
- */
- HeapTuple
- ExecRemoveJunk(junkfilter, slot)
- JunkFilter junkfilter;
- TupleTableSlot slot;
- {
- HeapTuple tuple;
- HeapTuple cleanTuple;
- AttributeNumberPtr cleanMap;
- TupleDescriptor cleanTupType;
- TupleDescriptor tupType;
- int cleanLength;
- Boolean isNull;
- int i;
- Size size;
- Datum *values;
- char *nulls;
- Datum values_array[64];
- char nulls_array[64];
-
- /* ----------------
- * get info from the slot and the junk filter
- * ----------------
- */
- tuple = (HeapTuple) ExecFetchTuple((Pointer) slot);
-
- tupType = (TupleDescriptor) get_jf_tupType(junkfilter);
- cleanTupType = (TupleDescriptor) get_jf_cleanTupType(junkfilter);
- cleanLength = get_jf_cleanLength(junkfilter);
- cleanMap = get_jf_cleanMap(junkfilter);
-
- /* ---------------------
- * Handle the trivial case first.
- * ---------------------
- */
- if (cleanLength == 0)
- return (HeapTuple) NULL;
-
- /* ---------------------
- * Create the arrays that will hold the attribute values
- * and the null information for the new "clean" tuple.
- *
- * Note: we use memory on the stack to optimize things when
- * we are dealing with a small number of tuples.
- * for large tuples we just use palloc.
- * ---------------------
- */
- if (cleanLength > 64) {
- size = cleanLength * sizeof(Datum);
- values = (Datum *) palloc(size);
-
- size = cleanLength * sizeof(char);
- nulls = (char *) palloc(size);
- } else {
- values = values_array;
- nulls = nulls_array;
- }
-
- /* ---------------------
- * Exctract one by one all the values of the "clean" tuple.
- * ---------------------
- */
- for (i=0; i<cleanLength; i++) {
- Datum d = (Datum)
- heap_getattr(tuple, InvalidBuffer, cleanMap[i], tupType, &isNull);
-
- values[i] = d;
-
- if (isNull)
- nulls[i] = 'n';
- else
- nulls[i] = ' ';
- }
-
- /* ---------------------
- * Now form the new tuple.
- * ---------------------
- */
- cleanTuple = heap_formtuple(cleanLength,
- cleanTupType,
- values,
- nulls);
-
- /* ---------------------
- * We are done. Free any space allocated for 'values' and 'nulls'
- * and return the new tuple.
- * ---------------------
- */
- if (cleanLength > 64) {
- pfree(values);
- pfree(nulls);
- }
-
- return(cleanTuple);
- }
-
-